import { assignContentBlockFields, assignPageFields, dateFormat, sleep } from '@/utils/helpers'
import { getSiblingPageBlockList, getContentData } from '@/utils/parse'
import { StdPage } from '@/utils/parse/page'
import { StdBlock } from '@/utils/parse/block'
import { generateAnnexPage, generateContentPage, generateSiblingPage,generateAlgo } from '@/utils/parse'
import { headTypes, contentTypes, isAnnexByType } from '@/constants/structure'
import { uniq } from 'lodash'
import setExtStyle from '@/utils/extStyle'
import tinymce from 'tinymce'
import { v4 as uuid } from 'uuid'
import { updateDomain } from '@/utils/helpers'
import { Message } from 'element-ui'
import { getInitPageList } from '@/utils/init'
import { getTextWidth } from '@/utils/dom'


const state = {
  _id: 1,
  pageZoom: 1,
  templateId: null,
  isChief: false,
  currentUserInfo: {},
  filePropertyName: 'COMMON',
  publicFilePath: undefined,
  docSource: 1,
  docType: undefined,
  languageType: 'zh',
  refLanguageType: undefined,
  standardBaseInfo: null,
  ruleId: null,
  editingFormulaId: null,
  editingFormulaType: null,
  revisionLineIds: null,
  historyList: [],
  commentList: [],
  fileTypes: [],
  enableRevisionLine: false,
  isFormulaImage: false,
  editorRef: null,
  collaborateStatusChange: false,
  insertType: '',
  contentBlockList: [],
  currentStandard: {},
  referenceType: '',
  indexNodes: [],
  removeTermBlockId: undefined,
  termGuideObj: {
    guideIndex: 0,
    selections: []
  },
  termBlockList: [],
  termListTitleType: 'item1',
  abbrTableData: {},
  sidebar: {
    left: {
      collapse: false,
      activeNav: ''
    },
    right: {
      collapse: false,
      activeNav: ''
    }
  },
  currentPageId: null,
  permissions: {},
  editorConfig: {},
  currentNo: null,
  originalEditorConfig: {},
  canSave: false,
  editableIds: [],
  pageData: [],
  storeBlockList: [],
  ruleStructures: [],
  ruleFonts: [],
  revisionContentList: [],
  signatureInfoList: [],
  checkResult: {
    formatCheckResult: [],
    contentCheckResult: []
  },
  classifyList: [],
  keywordList: [],
  cooperateList: [],
  currentCooperator: null,
  editorPageList: [],
  unreadCount: '',
  variableAtt: null,
  editorVariableList: [],
  docInfo: {},
  provisionSelections:[],
  algoTemplateInfo:{},
  reportAlgos:[],
  variableCharptId:null,
  variableCharptId:null,
  variableTableDataId:null,
  tableVariables:null,
  allVariableContent:[],
  allVariables:[],
  docStatus:null,
  algoTemplateVars:[],
  algoPicVars:[],
  algosTablesVars:[]
}

const mutations = {
  SET_ALGO_TABLE_VARS(state, data){
    state.algosTablesVars = data || []
  },
  SET_ALGO_PIC_VARS(state, data){
    state.algoPicVars = data || []
  },
  SET_ALGO_TEMPLATE_VARS(state, data){
    state.algoTemplateVars = data || []
  },
  SET_ALL_VARIABLES(state, data){
    state.allVariables = data || []
  },
  SET_ALL_VARIABLE_CONTENT(state, data){
    state.allVariableContent = data || []
  },
  SET_TABLE_VARIABLES(state, data){
    if(data){
      state.tableVariables = data
    }
  },
  SET_VARIABLE_TABLE_DATAID(state, data){
    state.variableTableDataId = data
  },
  SET_PAGE_ZOOM(state, data) {
    state.pageZoom = data
  },
  SET_EDITOR_REF(state, instance) {
    state.editorRef = instance
  },
  SET_ADDED_PAGE(state, { data, pos }) {
    if (Array.isArray(data)) {
      state.editorPageList.splice(pos, 0, ...data)
      return
    }
    state.editorPageList.splice(pos, 0, data)
  },
  SET_REPLACED_PAGE(state, { data, pos }) {
    state.editorPageList.splice(pos, 1, data)
  },
  REMOVE_PAGE(state, { pageId, blockId }) {
    const pageIndex = state.editorPageList.findIndex(i => i.pageId === pageId || i.pageId === blockId)
    if (pageIndex > -1) {
      state.editorPageList.splice(pageIndex, 1)
    } else {
      throw new Error('删除页面异常：未找到页面')
    }
  },
  UPDATE_DOC_STRUCTURE(state) {
    // head page: 'cover', 'signature', 'revision', 'contents', 'foreword', 'introduction'
    const headPageData = getSiblingPageBlockList('head').map(assignPageFields)
    // content page: 'scope', 'design_basis', 'normative_references', 'terms_definitions', 'symbols_abbreviation', 'chapter'
    const contentPageData = getContentData().map(assignContentBlockFields)
    // tail page:  annex, 'reference', 'index'
    const tailPageData = getSiblingPageBlockList('tail').map(assignPageFields)
    state.pageData = [...headPageData, ...contentPageData, ...tailPageData]
    state.pageData = state.pageData.map((i) => {
      i.dataId = i.dataId || i.pageId // dataId用于左侧结构树的 nodeKey
      return i
    })
    console.debug('---UPDATE_DOC_STRUCTURE---')
    this.commit('xmleditor/UPDATE_LIST_TITLE')
    const { editContentType, entry } = state.editorConfig
    if (editContentType === 'document' && (entry === 'flow' || entry === 'preview')) {
      this.commit('xmleditor/SET_ENDLINE')
    }
    updateDomain()
    tinymce.activeEditor.undoManager.add()
  },
  UPDATE_LIST_TITLE(state) {
    const { setAttrib, select, setHTML, getParent } = tinymce.activeEditor.dom
    const en = this.getters.languageType === 'both'
    select('#tinymce>.page-wrapper .page-sheet .list-title').forEach((node) => {
      const map = this.getters.mapDataIdAndIndex
      const newDataIndex = map[node.dataset.id] || map[node.dataset.blockId]
      setAttrib(node, 'data-index', newDataIndex)
      const parent = getParent(node, '[data-type="terms"]')
      if (parent) {
        setAttrib(parent, 'data-content-number', newDataIndex)
      }
    })

    // 页码从目次开始算
    const contentsCount = state.pageData.filter((i) => i.pageType === 'contents')?.length || 1
    const isTermDoc = state.filePropertyName === 'TERM' // 如果是术语文档
    function walk(cur) {
      const prev = []
      function fn(list = []) {
        for (const item of list) {
          item.title = item.title?.trim()?.split(/\s+/g)?.[0]
          prev.push(item)
          fn(item.children)
        }
      }
      fn(cur.children)
      return prev
    }
    let pageNumber = 0
    setHTML(
      select('#contentsRowList'),
      state.pageData
        .filter((i) => {
          if (i.pageType) {
            return !['cover', 'signature', 'revision', 'contents'].includes(i.pageType)
          }
          return true
        })
        .reduce((prev, cur) => {
          prev.push(cur)
          // 目次中术语和定义在术语标准文档中单独处理
          if (cur.dataType === 'terms_definitions') {
            return isTermDoc ? [...prev, ...walk(cur)] : prev
          }
          if (cur.dataType === 'symbols_abbreviation') {
            return prev
          }
          if (cur?.children?.length) {
            prev = [...prev, ...cur.children]
          }
          return prev
        }, [])
        .map((item) => {
          if (item.pageType || !/item[1-4]/g.test(item.dataType)) {
            pageNumber++
          }
          return { ...item, pageNumber }
        })
        .reduce((prev, cur) => {
          let listTitleStyle = ''
          if (cur.dataIndex) {
            listTitleStyle = `style="padding-left: ${getTextWidth(cur.dataIndex, '12pt "Times New Roman"') + 14}px;"`
          }
          let listTitleText = cur.title
          if (en && cur.titleEn && !isAnnexByType(cur.pageType)) {
            listTitleText = cur.titleZh + '<span class="chapter-title-en">' + cur.titleEn + '</span>'
          }

          prev += `
          <div class="row link-row ${cur.dataIndex ? 'indexed' : ''}"
            data-referred-id="${cur.pageId || cur.blockId}"
            data-link-type="${cur.dataType || ''}">
            <div class="data-index" ${cur.dataIndex ? '' : 'style="display: none;"'}>${cur.dataIndex}</div>
            <div class="list-title" ${listTitleStyle}>${listTitleText}</div>
            <div class="dot-line"></div>
            <div class="page-number">${cur.pageNumber + contentsCount}</div>
          </div>`
          return prev
        }, '')
    )
  },
  SET_ENDLINE() {
    const { remove, select, createFragment, insertAfter, is } = tinymce.activeEditor.dom
    const endline = select('hr.endline')?.[0]
    const sel1 = '#tinymce>.page-wrapper .page-sheet:last-child .page_body *:last-child'
    const sel2 = '#tinymce>.page-wrapper .page-sheet:last-child .page-body *:last-child'
    if ((is(endline, sel1), is(endline, sel2))) return
    remove(select('hr.endline'))
    select('#tinymce>.page-wrapper .page-sheet').forEach((node, index, arr) => {
      if (index === arr.length - 1) {
        const lastNode = node.querySelector('.page-body>*:last-child') || node.querySelector('.page_body>*:last-child')
        lastNode && insertAfter(createFragment(`<hr class="endline" data-type="endline">`), lastNode)
      }
    })
  },
  SET_FOCUSED_LIST_TITLE(state, id) {
    state.currentPageId = id || null
  },
  SET_BLOCK_LIST(state, data) {
    state.storeBlockList = data
  },
  UPDATE_CONTENT_INDEX(state) {
    //
    state._id++
  },
  SET_EDITING_FORMULA(state, { id, type }) {
    state.editingFormulaId = id
    state.editingFormulaType = type
  },
  SET_COMMENT_LIST(state, data) {
    state.commentList = data
  },
  CHANGE_SIDEBAR_ACTIVE_NAV(state, { side, activeNav }) {
    state.sidebar[side].activeNav = activeNav
  },
  CHANGE_SIDEBAR_ACTIVE_COLLAPSE(state, { side, collapse }) {
    state.sidebar[side].collapse = collapse
  },
  SET_COLLABORATE_STATUS_CHANGE(state, data) {
    state.collaborateStatusChange = data
  },
  SET_TERM_BLOCK_LIST(state, list) {
    state.termBlockList = list
  },
  SET_REMOVE_TERM_BLOCK_ID(state, id) {
    state.removeTermBlockId = id
  },
  async REMOVE_TERM_BLOCK(state) {
    const blockId = state.removeTermBlockId
    const doms = tinymce.activeEditor.dom.select(`[data-block-id="${blockId}"]`)
    if (doms.length) {
      console.log(doms.length)
      tinymce.activeEditor.dom.remove(doms)
    }
    const index = state.termBlockList.findIndex((i) => i.blockId === blockId)
    if (index > -1) {
      console.debug(`---remove term block: ${blockId}---`)
      state.termBlockList.splice(index, 1)
      tinymce.activeEditor.fire('termsUpdated')
    }
  },
  SET_TERM_LIST_TITLE_TYPE(state, type) {
    state.termListTitleType = type
  },
  SET_ABBR_TABLE_DATA(state, data) {
    state.abbrTableData = data
  },
  SET_ABBR_BLOCK_LIST(state, list) {
    if (!state.abbrTableData.blockId) {
      state.abbrTableData.blockId = uuid()
      state.abbrTableData.dataType = 'abbreviation'
    }
    state.abbrTableData = { ...state.abbrTableData, abbrData: list }
  },
  SET_FILE_PROPERTY_NAME(state, type) {
    // 0 COMMON 1 TERM 2 ABBR 3 ETSI prop == '1' ? 'TERM' : prop == '2' ? 'ABBR' : 'COMMON'
    let typeName = 'COMMON'
    if (type == '1') {
      typeName = 'TERM'
    } else if (type == '2') {
      typeName = 'ABBR'
    } else if (type == '3') {
      typeName = 'ETSI'
    }
    state.filePropertyName = typeName
  },
  async UPDATE_TERMS() {
    const bm = tinymce.activeEditor.selection.getBookmark()
    const termBlockNodes = tinymce.activeEditor.dom.select('.term-block')
    if (termBlockNodes?.length) {
      tinymce.activeEditor.dom.remove(termBlockNodes)
    }
    // 1. 如果没有术语，新创建DOM
    // 1.1 TODO: 判断光标所在位置是否能够插入内容
    // 1.2 判断插入的位置的标题级别
    console.debug('===UPDATE_TERMS Bookmark===', bm)
    // 1.3 生成DOM √
    await sleep()
    tinymce.activeEditor.selection.moveToBookmark(bm)
    const dom = document.querySelector('#termsTemplate')
    // 1.4 插入DOM √
    tinymce.activeEditor.insertContent(dom.innerHTML)
    // 2. 保存时将术语内容添加到结果中 √
    // 3. 刷新页面后，将术语内容回显到页面中 √
    // 4. 如果有术语，则更新DOM √
    // 4.1 先移除原有的术语 √
    // 4.2 再创建新的术语 √
    tinymce.activeEditor.fire('termsUpdated')
  },
  SET_TERM_GUIDE(state, obj) {
    state.termGuideObj = obj
  },
  async UPDATE_TERMS2() {
    const editor = tinymce.activeEditor
    const nodeSelector = '[data-content-page-type="terms_definitions"] .page_body>:not([data-type="terms_definitions"])'
    editor.dom.remove(editor.dom.select(nodeSelector))
    console.debug('===UPDATE_TERMS===')
    await sleep()
    const chapterPara = editor.getDoc()?.querySelector(`[data-type="terms_definitions"]`)
    const dom = document.querySelector('#termsTemplate')
    const paragraph = editor.dom.create('p')
    editor.dom.insertAfter(paragraph, chapterPara)
    await sleep()
    const nextPara = editor.getDoc()?.querySelector(`[data-type="terms_definitions"]+p`)
    nextPara.outerHTML = dom.innerHTML
    tinymce.activeEditor.fire('termsUpdated')
    tinymce.activeEditor.fire('insertTerms')
  },
  async UPDATE_ABBRS() {
    const editor = tinymce.activeEditor
    const sel = '[data-content-page-type="symbols_abbreviation"] .page_body>:not([data-type="symbols_abbreviation"])'
    const sel0 = '[data-content-page-type="symbols_abbreviation"] .page_footnote'
    const sel1 = `[data-content-page-type="symbols_abbreviation"] .page_body>[data-type="symbols_abbreviation"]`
    editor.dom.remove(editor.dom.select(`${sel},${sel0}`))
    await sleep()
    const dom = editor.dom.createFragment(document.querySelector('#abbrTemplate').innerHTML)
    editor.dom.insertAfter(dom, editor.getDoc()?.querySelector(sel1))
  },
  SET_INSERT_TYPE(state, data) {
    state.insertType = data
  },
  SET_CONTENT_BLOCKLIST(state, list) {
    state.contentBlockList = list
  },
  SET_CURRENT_STANDARD(state, row) {
    state.currentStandard = row
  },
  SET_REFERENCE_TYPE(state, data) {
    state.referenceType = data
  },
  SET_INDEX_NODES(state, data) {
    state.indexNodes = data
    setTimeout(() => tinymce.activeEditor.fire('updateIndex'))
  },
  INIT_EDITOR_CONFIG(state, data) {
    state.editorConfig = data
  },
  INIT_ORIGINAL_EDITOR_CONFIG(state, data) {
    state.originalEditorConfig = data
  },
  SET_CURRENT_DOC_NO(state, data) {
    state.currentNo = data
  },
  ADD_NEW_PAGE_EDITABLE(state, pageId) {
    !state.editableIds.includes(pageId) && state.editableIds.push(pageId)
  },
  REMOVE_PAGE_EDITABLE(state, pageId) {
    const idx = state.editableIds.indexOf(pageId)
    if (idx > -1) {
      state.editableIds.splice(idx, 1)
      console.log('===REMOVE_PAGE_EDITABLE===', pageId)
    }
  },
  SET_EDITABLE_IDS(state, data) {
    state.editableIds = data
  },
  SET_TEMPLATE_ID(state, data) {
    state.templateId = data
  },
  SET_ISCHIEF(state, data) {
    state.isChief = !!data
  },
  SET_CURRENT_USERINFO(state, data) {
    state.currentUserInfo = data || {}
  },
  SET_STANDARD_BASE_INFO(
    state,
    data = {
      classification: '中国商用飞机有限责任公司XXX',
      classificationEn: 'XXX OF COMMERCIAL AIRCRAFT CORPORATION OF CHINA,LTD.',
      compileUnit: 'XXX',
      compileUnitEn: 'XXX',
      implementationDate: 'XXXX-XX-XX',
      publishDate: 'XXXX-XX-XX',
      secretLevel: 'XX',
      standardName: 'XXXX',
      standardNameEn: 'XXXX',
      standardNo: 'XXX',
      standardVersion: 'X'
    }
  ) {
    state.standardBaseInfo = data
  },
  SET_RULE_ID(state, data) {
    state.ruleId = data
  },
  SET_REVISION_LINE_IDS(state, data = []) {
    state.revisionLineIds = uniq(data)
  },
  SET_REVISION_LINE_ENABLE(state, data) {
    state.enableRevisionLine = data
  },
  SET_FIGURE_FORMULA_INSERTING(state, flag = false) {
    state.isFormulaImage = flag
  },
  SET_REVISION(state, data = []) {
    state.revisionContentList = data.map((i) => ({ ...i, revisionDate: dateFormat(i.revisionDate) }))
  },
  SET_PERMISSIONS(state, data) {
    state.permissions = data
  },
  async SET_SIGNATURE_USERS(_, data = []) {
    await sleep() // DOM仍未渲染完成，需要到下一次宏任务结束后
    tinymce.activeEditor.dom.select('#tinymce .page-sheet.signature [data-sign-type]').forEach((node) => {
      const sign = data?.find((item) => item?.type === node?.dataset?.signType)
      if (sign) {
        const signTime = dateFormat(sign.signTime)
        node.innerText = `${sign.signUser} ${signTime}`
      }
    })
  },
  SET_SIGNATURE_INFO(state, data = []) {
    state.signatureInfoList = []
    const list = state.signatureInfoList
    // 如果数量少于 6 行 * 3
    if (data.length < 18) {
      data = [...data, ...Array.from({ length: 18 - data.length }).fill({})]
    } else if (data.length > 18) {
      // 大于 18 个时，补足3的倍数个
      const n = data.length % 3
      if (n) {
        data = [...data, ...Array.from({ length: 3 - n }).fill({})]
      }
    }
    for (let i = 0; i < data.length; i++) {
      // 每3个一组，每个的公司部门、用户时间拆分成两个元素
      if (i % 3 === 0) {
        list.push([])
      }
      const o = data[i]
      list[list.length - 1].push([o.company, o.department], [o.signUser, o.signTime])
    }
  },
  SET_HISTORY_LIST(state, data) {
    state.historyList = data
  },
  SET_CHECK_RESULT(state, data) {
    state.checkResult = data
  },
  SET_CLASSIFY_LIST(state, data) {
    state.classifyList = data
  },
  SET_KEYWORD_LIST(state, data) {
    state.keywordList = data
  },
  SET_COOPERATE_LIST(state, data) {
    state.cooperateList = data
  },
  SET_CURRENT_COOPERATOR(state, data) {
    state.currentCooperator = data
  },
  SET_RULE_STRUCTURES(state, data = []) {
    state.ruleStructures = data
  },
  SET_RULE_FONTS(state, data = []) {
    state.ruleFonts = data
    setExtStyle()
  },
  SET_DEPEND_FILETYPES(state, data = []) {
    state.fileTypes = data
  },
  SET_PAGE_PURE_HTML() {
    const editor = tinymce.activeEditor
    editor.dom.select('#tinymce>.page-wrapper .page-sheet').forEach((node) => {
      editor.dom.removeClass(node, 'noneditable')
      editor.dom.setAttrib(node, 'contenteditable', null)
      // 权限控制，设置不能编辑
      node.querySelectorAll('div, p, span, table, figure, sup, sub').forEach((i) => {
        editor.dom.setAttrib(i, 'contenteditable', null)
      })
    })
  },
  SET_PAGE_NONEDITABLE(state) {
    const editor = tinymce.activeEditor
    editor.dom.select('#tinymce>.page-wrapper .page-sheet').forEach((node) => {
      if (state.editableIds?.length && !state.editableIds.includes(node.dataset.pageId)) {
        editor.dom.addClass(node, 'noneditable irremovable')
        editor.dom.setAttrib(node, 'contenteditable', false)
        // 权限控制，设置不能编辑
        node.querySelectorAll('div, p, span, table, img, sup, sub').forEach((i) => {
          editor.dom.setAttrib(i, 'contenteditable', false)
        })
      }
    })
  },
  SET_DOCTYPE(state, docType) {
    state.docType = docType
  },
  SET_DOC_INFO(state, data) {
    state.docInfo = data
  },
  async INIT_EDITOR_DATA(state, data) {
    if (state.editorConfig.editContentType === 'block' || state.editorConfig.editContentType === 'collect') {
      const blockList = [new StdBlock({ dataType: 'blank_page' }), ...data]
      state.editorPageList = [new StdPage({ pageType: 'content', blockList })]
      this.commit('xmleditor/UPDATE_CONTENT_INDEX')
      return
    }
    console.log("初始化空白文章---init");
    console.log(data)
    if (data && data?.pageList?.length) {
      state.editorPageList = getInitPageList(data);
    } else {
        const headPages = headTypes.map(generateSiblingPage)
        const contentPages = contentTypes.map(generateContentPage)
        const annexPages = ['normativeAnnex', 'informativeAnnex'].map(generateAnnexPage)
        const tailPages = ['reference'].map(generateSiblingPage)
        state.editorPageList = [...headPages, ...contentPages, ...annexPages, ...tailPages]
        const newPageIds = state.editorPageList.map((i) => i.pageId)
        console.log("初始化空白文章");
        console.log(state.editorPageList)
        this.commit('xmleditor/SET_EDITABLE_IDS', newPageIds)
    }
    this.commit('xmleditor/UPDATE_CONTENT_INDEX')
  },
  SET_DOC_SOURCE(state, data = 1) {
    if (typeof data === 'number') {
      state.docSource = data
    } else if (typeof data === 'string' && /^\d+$/g.test(data)) {
      state.docSource = parseInt(data)
    } else {
      console.warn('===错误的source数据===')
    }
    if (this.getters.entry === 'htmlpreview') {
      if (this.getters._iframe) return
      if (data === 2) {
        Message({
          message: '本页面展示内容基于历史数据解析生成，仅供参考，正式依据参照本标准pdf原文。',
          type: 'warning',
          showClose: true,
          duration: 0
        })
      }
    }
  },
  SET_HAS_PRE_CHANGE_FILES(_, flag) {
    if (this.getters.entry === 'htmlpreview') {
      if (this.getters._iframe) return
      if (flag === true || flag === 'true') {
        Message({ message: '注意，本标准存在标准修改单', type: 'warning', showClose: true, offset: 60 })
      }
    }
  },
  SET_PUBLIC_FILE_PATH(state, data) {
    state.publicFilePath = data
  },
  SET_CAN_SAVE(state) {
    state.canSave = true
  },
  SET_LANGUAGE_TYPE(state, data) {
    state.languageType = data
  },
  SET_REF_LANGUAGE_TYPE(state, data) {
    state.refLanguageType = data
  },
  SET_UNREAD_COUNT(state, data = 0) {
    state.unreadCount = data === '0' || !data ? '' : data
  },
  //缓存变量属性
  SET_VARIABLE_ATT(state, data) {
    state.variableAtt = data;
  },
  SET_EDITOR_VARIABLE_LIST(state, data) {
    state.editorVariableList = data
  },
  SET_PROVISION_SELECTIONS(state, data) {
    state.provisionSelections = data
  },
  // 生成报告选择的算法分析列表
  SET_REPORT_ALGOS(state,data){
    state.reportAlgos = [...data];
  },
  //缓存章节数据
  SET_VARIABLE_CHARPT_ID(state,data){
    state.variableCharptId =data;
  },
  //缓存文章状态
  SET_DOC_STATUS(state,data){
    state.docStatus =data;
  }
}


export default {
  namespaced: true,
  state,
  mutations,
}
